/**
 *  Copyright (c) 2011, IPC Studio, USTC, All rights reserved
 *  FileName: Lrc.cpp
 *  Author: chengximing1989@gmail.com
 *  DateCreated: 2011-9-28
 */

#include "../include/Lrc.h"
#include "../include/Log.h"

LIBLYRICS_NAMESPACE_BEGIN

CLrc::CLrc(void)
{
}

CLrc::~CLrc(void)
{
}

bool CLrc::OpenLyrics(string filename)
{
	m_plrcfile = fopen(filename.c_str(), "rb");

	if(!m_plrcfile)
	{
		//cout<<"Can't open "<<filename<<" file"<<endl;
		string logmsg = "Can't open ";
		logmsg += filename;
		logmsg += " file\n";
		CLog::LogDefault(LOG_ERROR, logmsg.c_str());
		return false;
	}

	if(!TestLyricsfile(filename))
	{
		//cout<<"The file to be opened is not a real lyrics file"<<endl;
		string logmsg = "The file to be opened is not a real lyrics file\n";
		CLog::LogDefault(LOG_ERROR, logmsg.c_str());
		return false;
	}
#ifdef _DEBUG
	//cout<<"Open "<<filename<<" successfully"<<endl;
	string logmsg = "Open ";
	logmsg += filename;
	logmsg += " successfully\n";
	CLog::LogDefault(LOG_INFO, logmsg.c_str());
#endif

	m_pencoder->ReadFileIntoRam(m_plrcfile, m_alllrc);
	int len = m_alllrc.length();
	if(len > 0)
	{
#ifdef _DEBUG
		//cout<<"Read "<<filename<<" successfully"<<endl;
		string logmsg = "Read ";
		logmsg += filename;
		logmsg += " successfully\n";
		CLog::LogDefault(LOG_INFO, logmsg.c_str());
#endif
	}
	/*for(int k=len-1; k>0; k--)
	{
		if(alllrc.at(k) == 0x0a)
		{
			alllrc = alllrc.erase(k,1);
		}
	}*/
	if(!LoadLyricsfile(filename))
	{
		//cout<<"Can't load "<<filename<<" file"<<endl;
		string logmsg = "Can't load ";
		logmsg += filename;
		logmsg += " file\n";
		CLog::LogDefault(LOG_ERROR, logmsg.c_str());
		return false;
	}

	return true;
}

bool CLrc::TestLyricsfile(string filename)
{
	//I put nothing in this function, as I have not found a good way
	return true;
}

bool CLrc::LoadLyricsfile(string filename)
{
	int istart = 0,iend = -1;
	
	while((istart=m_alllrc.find("[",iend+1))!=-1)
	{
		iend =m_alllrc.find("]",istart+1);
		if(istart == -1) break;
		if(iend == -1) break;
		if(iend < istart) break;
		string head = m_alllrc.substr(istart+1, 3);
		string test = m_alllrc.substr(istart+1, 1);
		transform(head.begin(),head.end(),head.begin(),(int(*)(int))tolower);
		if(head == "ti:")
		{
			string headinfo = "Title:";
			headinfo += m_alllrc.substr(istart+4, iend-istart-4);
			m_veclrcheadinfo.push_back(headinfo);
		}
		else if(head == "ar:")
		{
			string headinfo = "Artist:";
			headinfo += m_alllrc.substr(istart+4, iend-istart-4);
			m_veclrcheadinfo.push_back(headinfo);
		}
		else if(head == "al:")
		{
			string headinfo = "Album:";
			headinfo += m_alllrc.substr(istart+4, iend-istart-4);
			m_veclrcheadinfo.push_back(headinfo);
		}
		else if(head == "by:")
		{
			string headinfo = "LyricsBy:";
			headinfo += m_alllrc.substr(istart+4, iend-istart-4);
			m_veclrcheadinfo.push_back(headinfo);
		}
		else if(m_alllrc.substr(istart+1, 7) == "offset:")
		{
			string time = m_alllrc.substr(istart+8, iend-istart-8);
			m_offset = atoi(time.c_str());
		}
		else if((test >= "0")&&(test <= "9"))
		{
			StorelineLyrics(istart,iend);
		}
	}
	/*if((istart == -1)||(iend == -1))
		return false;*/
#ifdef _DEBUG
	//cout<<"Load "<<filename<<" successfully"<<endl;
	string logmsg = "Load ";
	logmsg += filename;
	logmsg += " successfully\n";
	CLog::LogDefault(LOG_INFO, logmsg.c_str());
#endif

	/*vector<LrcRecord>::iterator itVector;
	for(itVector = veclrcrec.begin(); itVector != veclrcrec.end(); itVector++)
	cout<<itVector->lrctxt<<endl;*/
	return true;
}

bool CLrc::ReadTimeLabel(int istart, int iend, string& strMi, string& strSec, string& strmSec)
{
	int temp_colon = -1, temp_dot = -1, temp_colon2 = -1;
	temp_colon = m_alllrc.substr(0, iend).find(":", istart+1);
	temp_colon2 = m_alllrc.substr(0, iend).find(":", temp_colon+1);
	strMi = m_alllrc.substr(istart+1, temp_colon-istart-1);
	if(temp_colon2 == -1)
	{
		temp_dot = m_alllrc.substr(0, iend).find(".", temp_colon+1);
		strSec = m_alllrc.substr(temp_colon+1, temp_dot-temp_colon-1);
		strmSec = m_alllrc.substr(temp_dot+1, iend-temp_dot-1);
		if(strmSec.length() == 2)
			strmSec += "0";
	}
	else
	{
		strSec = m_alllrc.substr(temp_colon+1, temp_colon2-temp_colon-1);
		strmSec = m_alllrc.substr(temp_colon2+1, iend-temp_colon2-1);
	}
	return true;
}

void CLrc::StorelineLyrics(int& istart,int& iend)
{
	LrcRecord lrcrec[20];
	int iLrcRecord = 0;
	
	while((istart = m_alllrc.find("[",istart))!=-1)
	{
		string strMi,strSec,strmSec;
		
		if(istart == -1) break;
		if(iend == -1) break;
		if(iend < istart) break;
		ReadTimeLabel(istart, iend, strMi, strSec, strmSec);
		lrcrec[iLrcRecord].time = atoi(strMi.c_str())*60*1000 + atoi(strSec.c_str())*1000
			+ atoi(strmSec.c_str());
		iLrcRecord++;
		int itxtend = m_alllrc.find("[",iend+1)-1;
		string testtxt = m_alllrc.substr(iend+1, itxtend-iend);
		string temp = testtxt;
		for(int k=testtxt.length()-1; k>=0; k--)
		{
			if((temp.at(k) == 32)||(temp.at(k) == 9))
			{
				temp.erase(k,1);
			}
		}
		if(!temp.empty())
		{
			// under windows, remove the last 0x0d0x0a
			if(testtxt.at(testtxt.length() - 1) == 0x0a)
				testtxt.erase(testtxt.length() - 1, 1);
			if(testtxt.at(testtxt.length() - 1) == 0x0d)
				testtxt.erase(testtxt.length() - 1, 1);
			for(int k=0; k<iLrcRecord; k++)
			{
				lrcrec[k].lrctxt = testtxt;
				//cout<<testtxt<<endl;
			}
			break;
		}
		iend = m_alllrc.find("]",iend+1);
		istart++;
	}

	for(int i=0; i<iLrcRecord; i++)
	{
		bool isinsert = false;
		for(unsigned int k=0; k < m_veclrcrec.size(); k++)
		{
			if(lrcrec[i].time < m_veclrcrec.at(k).time)
			{
				m_veclrcrec.insert(m_veclrcrec.begin()+k, 1, lrcrec[i]);
				isinsert = true;
				break;
			}
		}
		if(!isinsert)
			m_veclrcrec.push_back(lrcrec[i]);
	}
	// This test of iend fixed endless loop bug in 1.0.0.1 beta
	if(iend == -1)
		iend = m_alllrc.length() - 1;
}

string CLrc::GetLrctxt(int time)
{
	vector<LrcRecord>::iterator itVector;
	if(m_veclrcrec.size() > 1)
	{
		for(itVector = m_veclrcrec.begin(); itVector != m_veclrcrec.end()-1; itVector++)
		{
			if((time >= itVector->time)&&(time < (itVector+1)->time))
			{
				return itVector->lrctxt;
			}
		}
		// Fixed the bug which could not get the last lyrics line in 1.0.0.1 beta
		if(itVector == m_veclrcrec.end() - 1)
		{
			if(time >= itVector->time)
				return itVector->lrctxt;
		}
	}
	else if(m_veclrcrec.size() == 0)
		return "";
	else
	{
		if(time >= m_veclrcrec.begin()->time)
			return m_veclrcrec.begin()->lrctxt;
		else
			return "";
	}
	return "";
}

LIBLYRICS_NAMESPACE_END